package com.xbjtech.controller;

import java.util.Iterator;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.constraints.NotBlank;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;

import com.google.code.kaptcha.Constants;
import com.xbjtech.shiro.MobileCodeToken;
import lombok.extern.slf4j.Slf4j;

@Controller
@Slf4j
@Validated
public class LoginController {
	
	@GetMapping("/login")
	public String login() {
		return "login";
	}
	
	@PostMapping("/login")
	public String login(
			@NotBlank(message = "用户名不能为空") String username, 
			@NotBlank(message = "密码不能为空") String password,
			@NotBlank(message = "验证码不能为空") String code,
			Model model) {
		Subject currentUser = SecurityUtils.getSubject();
		Session session = currentUser.getSession();
		if (!code.equalsIgnoreCase(session.getAttribute(Constants.KAPTCHA_SESSION_KEY) + "")) {
			model.addAttribute("errorMessage", "验证码不正确");
			return "login";
		}
		log.info("username:{},password:{}", username, password);
		// 服务器端的校验
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        token.setRememberMe(true);
        try {
        	log.info("hashcode:{}", token.hashCode());
            currentUser.login(token);
            return "redirect:/index";
        } catch (UnknownAccountException uae) {
            log.info("There is no user with username of " + token.getPrincipal());
            model.addAttribute("errorMessage", uae.getMessage());
            return "login";
        } catch (IncorrectCredentialsException ice) {
            log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            model.addAttribute("errorMessage", "密码不正确");
            return "login";
        } catch (LockedAccountException lae) {
            log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                    "Please contact your administrator to unlock it.");
            model.addAttribute("errorMessage", lae.getMessage());
            return "login";
        } catch (AuthenticationException ae) {
        	model.addAttribute("errorMessage", "登录异常");
        	return "login";
        }
	}
	
	@PostMapping("/mobilelogin")
	public String mobileLogin(String mobile, String code, Model model) {
		log.info("mobile:{}, code:{}", mobile, code);
		
		// 认证
		Subject currentUser = SecurityUtils.getSubject();
		// 服务器端的校验
        MobileCodeToken token = new MobileCodeToken(mobile, code);
        try {
        	log.info("hashcode:{}", token.hashCode());
            currentUser.login(token);
            return "redirect:/index";
        } catch (UnknownAccountException uae) {
            log.info("There is no user with username of " + token.getPrincipal());
            model.addAttribute("errorMessage", uae.getMessage());
            return "login";
        } catch (IncorrectCredentialsException ice) {
            log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            model.addAttribute("errorMessage", "验证码不正确");
            return "login";
        } catch (LockedAccountException lae) {
            log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                    "Please contact your administrator to unlock it.");
            model.addAttribute("errorMessage", lae.getMessage());
            return "login";
        } catch (AuthenticationException ae) {
        	model.addAttribute("errorMessage", "登录异常");
        	return "login";
        }
		
		
	}
	
//	@RequestMapping("/logout")
//	public String logout() {
//		Subject currentUser = SecurityUtils.getSubject();
//		currentUser.logout();
//		return "redirect:/login";
//	}
	
	@ExceptionHandler({ConstraintViolationException.class})
	public ModelAndView ex(ConstraintViolationException e) {
		ModelAndView mv = new ModelAndView("login");
		Iterator<ConstraintViolation<?>> iterator = e.getConstraintViolations().iterator();
		while(iterator.hasNext()) {
			ConstraintViolation<?> next = iterator.next();
			mv.addObject(next.getPropertyPath() + "", next.getMessage());
		}
		return mv;
	}
	
}
